/**
 * @file test_command_queue.cpp
 * @author 心流 (iFlow CLI)
 * @brief 测试OpenCL命令队列创建和管理功能
 * @version 0.1
 * @date 2025-11-26
 *
 * @copyright Copyright (c) 2025
 *
 */
#define BOOST_TEST_MODULE TestCommandQueue
#include <CL/cl.h>

#include <boost/format.hpp>
#include <boost/test/included/unit_test.hpp>
#include <boost/timer/timer.hpp>
#include <vector>

#include "test_fixture.hpp"
#include "utility.hpp"

// 测试使用clCreateCommandQueue创建命令队列
BOOST_AUTO_TEST_CASE(TestCreateCommandQueue)
{
    CLTestFixture fixture;
    cl_context    context = fixture.context_;
    cl_device_id  device  = fixture.device_;
    BOOST_CHECK(context != nullptr);
    BOOST_CHECK(device != nullptr);

    // 创建命令队列（旧版API）
    cl_int           err   = CL_SUCCESS;
    cl_command_queue queue = clCreateCommandQueue(context, device, 0, &err);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue != nullptr);

    // 验证命令队列是否有效
    cl_command_queue_info param_name    = CL_QUEUE_CONTEXT;
    cl_context            queue_context = nullptr;
    err                                 = clGetCommandQueueInfo(queue,
                                CL_QUEUE_CONTEXT,
                                sizeof(queue_context),
                                &queue_context,
                                nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue_context != nullptr);

    // 比较队列的上下文是否与原始上下文匹配
    BOOST_CHECK(queue_context == context);

    // 清理
    err = clReleaseCommandQueue(queue);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
}

// 测试使用clCreateCommandQueueWithProperties创建命令队列（新版本API）
BOOST_AUTO_TEST_CASE(TestCreateCommandQueueWithProperties)
{
    CLWrapper cl;
    bool      init_result = cl.Init();
    BOOST_CHECK(init_result == true);

    cl_context   context = cl.GetContext();
    cl_device_id device  = cl.GetDeviceID();
    BOOST_CHECK(context != nullptr);
    BOOST_CHECK(device != nullptr);

    // 使用属性创建命令队列（新API）
    cl_int           err = CL_SUCCESS;
    cl_command_queue queue =
        clCreateCommandQueueWithProperties(context, device, nullptr, &err);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue != nullptr);

    // 验证命令队列
    cl_context queue_context = nullptr;
    err                      = clGetCommandQueueInfo(queue,
                                CL_QUEUE_CONTEXT,
                                sizeof(queue_context),
                                &queue_context,
                                nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue_context == context);

    cl_device_id queue_device = nullptr;
    err                       = clGetCommandQueueInfo(
        queue, CL_QUEUE_DEVICE, sizeof(queue_device), &queue_device, nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue_device == device);

    // 清理
    err = clReleaseCommandQueue(queue);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
}

// 测试CLWrapper中的命令队列管理
BOOST_AUTO_TEST_CASE(TestCLWrapperCommandQueue)
{
    CLTestFixture fixture;

    // 验证CLWrapper创建的命令队列是否有效
    cl_command_queue queue = fixture.queue_;
    BOOST_CHECK(queue != nullptr);

    // 验证队列属性
    cl_context queue_context = nullptr;
    cl_int     err           = clGetCommandQueueInfo(queue,
                                       CL_QUEUE_CONTEXT,
                                       sizeof(queue_context),
                                       &queue_context,
                                       nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue_context == fixture.context_);

    cl_device_id queue_device = nullptr;
    err                       = clGetCommandQueueInfo(
        queue, CL_QUEUE_DEVICE, sizeof(queue_device), &queue_device, nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue_device == fixture.device_);

    cl_uint reference_count = 0;
    err                     = clGetCommandQueueInfo(queue,
                                CL_QUEUE_REFERENCE_COUNT,
                                sizeof(reference_count),
                                &reference_count,
                                nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK_GT(reference_count, 0);

    // 检查队列属性（如果是新版本的OpenCL）
    cl_command_queue_properties properties = 0;
    err                                    = clGetCommandQueueInfo(
        queue, CL_QUEUE_PROPERTIES, sizeof(properties), &properties, nullptr);
    if (err == CL_SUCCESS)
    {
        // 检查是否成功获取了属性值
        // 在某些实现中，这可能返回错误，这在旧版本的OpenCL中是正常的
    }
}

// 测试命令队列信息查询
BOOST_AUTO_TEST_CASE(TestCommandQueueInfo)
{
    CLTestFixture fixture;

    cl_command_queue queue = fixture.queue_;
    BOOST_CHECK(queue != nullptr);

    // 测试查询命令队列上下文
    cl_context context = nullptr;
    cl_int     err     = clGetCommandQueueInfo(
        queue, CL_QUEUE_CONTEXT, sizeof(context), &context, nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(context != nullptr);

    // 测试查询命令队列设备
    cl_device_id device = nullptr;
    err                 = clGetCommandQueueInfo(
        queue, CL_QUEUE_DEVICE, sizeof(device), &device, nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(device != nullptr);

    // 测试查询引用计数
    cl_uint ref_count = 0;
    err               = clGetCommandQueueInfo(queue,
                                CL_QUEUE_REFERENCE_COUNT,
                                sizeof(ref_count),
                                &ref_count,
                                nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK_GT(ref_count, 0);
}

// 测试命令队列属性（如队列大小等）
BOOST_AUTO_TEST_CASE(TestCommandQueueProperties)
{
    CLTestFixture fixture;

    cl_context   context = fixture.context_;
    cl_device_id device  = fixture.device_;
    BOOST_CHECK(context != nullptr);
    BOOST_CHECK(device != nullptr);

    // 创建具有特定属性的命令队列
    cl_queue_properties props[] = {CL_QUEUE_PROPERTIES,
                                   0,  // 默认属性
                                   0};
    cl_int              err     = CL_SUCCESS;
    cl_command_queue    queue =
        clCreateCommandQueueWithProperties(context, device, props, &err);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue != nullptr);

    // 测试队列是否有效
    cl_context queue_context = nullptr;
    err                      = clGetCommandQueueInfo(queue,
                                CL_QUEUE_CONTEXT,
                                sizeof(queue_context),
                                &queue_context,
                                nullptr);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue_context == context);

    // 清理
    err = clReleaseCommandQueue(queue);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
}

// 测试命令队列错误处理
BOOST_AUTO_TEST_CASE(TestCommandQueueErrorHandling)
{
    CLWrapper cl;
    bool      init_result = cl.Init();
    BOOST_CHECK(init_result == true);

    cl_context   context = cl.GetContext();
    cl_device_id device  = cl.GetDeviceID();
    BOOST_CHECK(context != nullptr);
    BOOST_CHECK(device != nullptr);

    cl_int err = CL_SUCCESS;

    // 测试使用无效的上下文创建命令队列（应该失败）
    cl_command_queue queue =
        clCreateCommandQueueWithProperties(nullptr, device, nullptr, &err);
    BOOST_CHECK_NE(err, CL_SUCCESS);  // 应该失败
    BOOST_CHECK(queue == nullptr);

    // 测试使用无效的设备创建命令队列（应该失败）
    queue = clCreateCommandQueueWithProperties(context, nullptr, nullptr, &err);
    BOOST_CHECK_NE(err, CL_SUCCESS);  // 应该失败
    BOOST_CHECK(queue == nullptr);

    // 测试正常创建命令队列
    queue = clCreateCommandQueueWithProperties(context, device, nullptr, &err);
    BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    BOOST_CHECK(queue != nullptr);

    // 测试查询无效命令队列的信息（应该失败）
    cl_uint ref_count = 0;
    err               = clGetCommandQueueInfo(nullptr,
                                CL_QUEUE_REFERENCE_COUNT,
                                sizeof(ref_count),
                                &ref_count,
                                nullptr);
    BOOST_CHECK_NE(err, CL_SUCCESS);  // 应该失败

    // 正常清理命令队列
    if (queue)
    {
        err = clReleaseCommandQueue(queue);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    }
}

// 测试多个命令队列
BOOST_AUTO_TEST_CASE(TestMultipleCommandQueues)
{
    CLWrapper cl;
    bool      init_result = cl.Init();
    BOOST_CHECK(init_result == true);

    cl_context   context = cl.GetContext();
    cl_device_id device  = cl.GetDeviceID();
    BOOST_CHECK(context != nullptr);
    BOOST_CHECK(device != nullptr);

    const int                     num_queues = 3;
    std::vector<cl_command_queue> queues(num_queues);

    // 创建多个命令队列
    cl_int err = CL_SUCCESS;
    for (int i = 0; i < num_queues; i++)
    {
        queues[i] =
            clCreateCommandQueueWithProperties(context, device, nullptr, &err);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);
        BOOST_CHECK(queues[i] != nullptr);
    }

    // 验证每个队列
    for (int i = 0; i < num_queues; i++)
    {
        cl_context queue_context = nullptr;
        err                      = clGetCommandQueueInfo(queues[i],
                                    CL_QUEUE_CONTEXT,
                                    sizeof(queue_context),
                                    &queue_context,
                                    nullptr);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);
        BOOST_CHECK(queue_context == context);

        cl_uint ref_count = 0;
        err               = clGetCommandQueueInfo(queues[i],
                                    CL_QUEUE_REFERENCE_COUNT,
                                    sizeof(ref_count),
                                    &ref_count,
                                    nullptr);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);
        BOOST_CHECK_GT(ref_count, 0);
    }

    // 清理所有队列
    for (int i = 0; i < num_queues; i++)
    {
        err = clReleaseCommandQueue(queues[i]);
        BOOST_CHECK_EQUAL(err, CL_SUCCESS);
    }
}
